﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NMF.Expressions.Arithmetics
{
    internal class ObservableIntModulo : ObservableBinaryExpressionBase<int, int, int>
    {
        public ObservableIntModulo(IObservableExpression<int> left, IObservableExpression<int> right)
            : base(left, right) { }

        protected override int GetValue()
        {
            return Left.Value % Right.Value;
        }

        public override IObservableExpression<int> ApplyParameters(IDictionary<string, object> parameters)
        {
            return new ObservableIntModulo(Left.ApplyParameters(parameters), Right.ApplyParameters(parameters));
        }
    }

    internal class ObservableLongModulo : ObservableBinaryExpressionBase<long, long, long>
    {
        public ObservableLongModulo(IObservableExpression<long> left, IObservableExpression<long> right)
            : base(left, right) { }

        protected override long GetValue()
        {
            return Left.Value % Right.Value;
        }

        public override IObservableExpression<long> ApplyParameters(IDictionary<string, object> parameters)
        {
            return new ObservableLongModulo(Left.ApplyParameters(parameters), Right.ApplyParameters(parameters));
        }
    }

    internal class ObservableUIntModulo : ObservableBinaryExpressionBase<uint, uint, uint>
    {
        public ObservableUIntModulo(IObservableExpression<uint> left, IObservableExpression<uint> right)
            : base(left, right) { }

        protected override uint GetValue()
        {
            return Left.Value % Right.Value;
        }

        public override IObservableExpression<uint> ApplyParameters(IDictionary<string, object> parameters)
        {
            return new ObservableUIntModulo(Left.ApplyParameters(parameters), Right.ApplyParameters(parameters));
        }
    }


    internal class ObservableULongModulo : ObservableBinaryExpressionBase<ulong, ulong, ulong>
    {
        public ObservableULongModulo(IObservableExpression<ulong> left, IObservableExpression<ulong> right)
            : base(left, right) { }

        protected override ulong GetValue()
        {
            return Left.Value % Right.Value;
        }

        public override IObservableExpression<ulong> ApplyParameters(IDictionary<string, object> parameters)
        {
            return new ObservableULongModulo(Left.ApplyParameters(parameters), Right.ApplyParameters(parameters));
        }
    }

    internal class ObservableFloatModulo : ObservableBinaryExpressionBase<float, float, float>
    {
        public ObservableFloatModulo(IObservableExpression<float> left, IObservableExpression<float> right)
            : base(left, right) { }

        protected override float GetValue()
        {
            return Left.Value % Right.Value;
        }

        public override IObservableExpression<float> ApplyParameters(IDictionary<string, object> parameters)
        {
            return new ObservableFloatModulo(Left.ApplyParameters(parameters), Right.ApplyParameters(parameters));
        }
    }

    internal class ObservableDoubleModulo : ObservableBinaryExpressionBase<double, double, double>
    {
        public ObservableDoubleModulo(IObservableExpression<double> left, IObservableExpression<double> right)
            : base(left, right) { }

        protected override double GetValue()
        {
            return Left.Value % Right.Value;
        }

        public override IObservableExpression<double> ApplyParameters(IDictionary<string, object> parameters)
        {
            return new ObservableDoubleModulo(Left.ApplyParameters(parameters), Right.ApplyParameters(parameters));
        }
    }
}
